/*
 * Created on Jun 10, 2005
 *
 */
package com.erclab.internal.xpresso.webapp.servlets;

import java.io.IOException;
import java.util.*;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.erclab.internal.xpresso.FormFactory;
import com.erclab.internal.xpresso.OptionsFactory;
import com.erclab.internal.xpresso.Resource;
import com.erclab.internal.xpresso.dataAccess.DataModifier;
import com.erclab.internal.xpresso.datavalidators.DataValidationError;
import com.erclab.internal.xpresso.exceptions.DataModificationException;
import com.erclab.internal.xpresso.exceptions.FormException;
import com.erclab.internal.xpresso.formelements.FormElement;
import com.erclab.internal.xpresso.forms.*;
import com.erclab.internal.xpresso.security.User;
import com.erclab.internal.xpresso.webapp.WebObjectFactory;

import org.apache.log4j.*;

/**
 * @author Enrique Rodriguez.
 *
 */
public class FormProcessor extends HttpServlet {

	//	Create the log for this class
	private static final Logger log = Logger.getLogger(FormProcessor.class);

	/* (non-Javadoc)
	 * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {
		doPost(request, response);
	}

	/* (non-Javadoc)
	 * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {
		
		HttpSession session = request.getSession();		
		User user = WebUserManagement.loadUser(session, request);	
		
		String fieldDescriptor = request.getParameter("fieldDescriptor");
		FormParameters parameters = new FormParameters();
		parameters.setParentKeyValue(request.getParameter("parentKeyValue"));
		parameters.setUniqueKeyValue(request.getParameter("uniqueKeyValue"));
		parameters.setAction(request.getParameter("action"));
		parameters.setUser(user);
		// parameters.setFormRequest(request);
		
		Form theForm = null;
		try {
			log.info("Loading form: " + request.getParameter("formName"));
			theForm = FormFactory.loadForm(request.getParameter("formName"));
		} catch (FormException e) {
			log.error("Could not load form '" + request.getParameter("formName") + "': " + e);
			throw new ServletException("Could not load form '" + request.getParameter("formName") + "': " + e);
		}
		this.setRequestParameters(request, parameters);
		theForm.setFormParameters(parameters);
		
		HashMap keyValues = new HashMap();
		boolean validData = true;
		
		if (fieldDescriptor == null){
			for (Iterator iter = theForm.getFormElements().iterator(); iter.hasNext();) {
				FormElement fe = (FormElement)iter.next();
				keyValues.put("Field" + fe.getIdFormElement(), request.getParameterValues("Field" + fe.getIdFormElement()));
				fe.setUserValue(request.getParameterValues("Field" + fe.getIdFormElement()));
				log.info("Field" + fe.getIdFormElement()+  " --> "+ request.getParameterValues("Field" + fe.getIdFormElement()));
				validData = validateData(fe);
			}
		} else {
			for (Iterator iter = theForm.getFormElements().iterator(); iter.hasNext();) {
				FormElement fe = (FormElement)iter.next();
				keyValues.put("Field" + fe.getIdFormElement(), request.getParameterValues("Field" + fe.getDestinationColumn()));
				fe.setUserValue(request.getParameterValues("Field" + fe.getDestinationColumn()));
				log.info("Field" + fe.getIdFormElement()+  " --> "+ request.getParameterValues("Field" + fe.getDestinationColumn()));
				validData = validateData(fe);
			}
		}
		
		if (!validData){
			try {
				DataValidationError e = new DataValidationError("");
				sendError(request, response, theForm, e);
				return;
			} catch (Exception e) {
				throw new ServletException("A problem after form validation: " + e);
			}
		}
		
		DataModifier dm = new DataModifier();
		try {
			dm.executeFormChange(theForm, keyValues);
		} catch (DataModificationException e) {
			log.error("A problem occurred trying to update or insert: " + e);
			throw new ServletException("A problem occurred trying to update or insert: " + e);
		} catch (DataValidationError e) {
			try {
				theForm.setValidationError(e);
				sendError(request, response, theForm, e);
				return;
			} catch (Exception e1) {
				throw new ServletException("A problem after form validation: " + e);
			}
		}
		response.sendRedirect(getForwardPage(theForm.getForwardUrl(), request));
	}

	protected void setRequestParameters(HttpServletRequest request, FormParameters parameters) {
		HashMap<String, String> requestParameters  = new HashMap<String, String>();
		
		Enumeration enumeration = request.getParameterNames();
		while(enumeration.hasMoreElements()){
			String name = (String)enumeration.nextElement();
			requestParameters.put(name, request.getParameter(name));			
		}
		parameters.setRequestParameters(requestParameters);
	}	

	protected void sendError(HttpServletRequest request, 
								HttpServletResponse response, 
								Form theForm, DataValidationError error) throws Exception, ServletException, IOException {
		FormResultSet frs = FormFactory.createForm(theForm);
		HttpSession session = request.getSession();
		OptionsFactory.loadFormOptions(theForm, (User)session.getAttribute("user"));
		request.setAttribute("Form", theForm);
		request.setAttribute("FormResultSet", frs);
		request.setAttribute(theForm.getFormName() + "ValidationError", error.toString());
		RequestDispatcher view = request.getRequestDispatcher(theForm.getViewHandler());
		view.forward(request, response);
	}

	private boolean validateData(FormElement fe) {
		boolean validData = true;
		if (fe.getDataValidator() != null ){
			try {
				fe.getDataValidator().validate(fe);
			} catch (DataValidationError e){
				validData = false;
				fe.setErrorMessage(e.toString());
			}
		}
		return validData;
	}

	/**
	 * @param string
	 * @return
	 */
	private String getForwardPage(String forwardUrl, HttpServletRequest request){
		String url = null;
		if(forwardUrl.equalsIgnoreCase("-param:previousUrl-")){
			url = (String)request.getSession().getAttribute("forwardUrl");
			if (url == null){
				return forwardUrl;
			}
		} else {
			if (forwardUrl != null){
				// TODO: replace with a utility class
				forwardUrl = forwardUrl.replaceAll("-param:uniqueKeyValue-", request.getParameter("uniqueKeyValue"));
				forwardUrl = forwardUrl.replaceAll("-param:actionValue-", request.getParameter("action"));
				
			}
			url = forwardUrl;
		}
		
		return url;
	}

}
